package com.gxgeek.interview.t1;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.joining;


/**
 * Created by gx on 2017/4/24.
 */
public class Written {


    //todo  尚未解决
    //    题目：古典问题：有一对兔子，从出生后第3个月起每个月都生一对兔子，
//    小兔子长到第三个月后每个月又生一对兔子，假如兔子都不死，问每个月的兔子总数为多少
    @Test//菲波拉契数列问题
    public void problem1() {
        Stream.iterate(new int [] {0,1},t->new int[]{t[1],t[0]+t[1]}).limit(24)
                .map(t->t[0]).forEach(System.out::println);
    }


    //题目：判断101-200之间有多少个素数，并输出所有素数。
    //程序分析：判断素数的方法：用一个数分别去除2到sqrt(这个数)，如果能被整除，
    // 则表明此数不是素数，反之是素数。
    @Test
    public void problem2() {
        String a = IntStream.rangeClosed(101, 200).filter(Written::isPrime).boxed().map(String::valueOf).collect(joining(","));
        System.out.println(a);
    }

    //判断是否非素数
    public static boolean isPrime(int s) {
        boolean flag = true;
        if (s < 2) {
            flag = false;
        }
        for (int i = 2; i < Math.sqrt(s); i++) {
            if (s % i == 0) {
                flag = false;
            }
        }
        return flag;
    }


    //【程序3】
    //题目：打印出所有的 "水仙花数 "，所谓 "水仙花数 "是指一个三位数，其各位数字立方和等于该数本身。
    // 例如：153是一个 "水仙花数 "，因为153=1的三次方+5的三次方+3的三次方。
    @Test
    public void problem3() {
        String s = IntStream.rangeClosed(100, 999).filter(Written::isNarcissus).boxed()
                .map(String::valueOf).collect(joining(","));
        System.out.println(s);
    }

    //判断是否是水仙花数
    public static boolean isNarcissus(int s) {
        int a = s / 100; //百位数
        int b = s % 100 / 10; //十位数
        int c = s % 10;  // 个位数
        return add(Math.pow(a, 3), Math.pow(b, 3), Math.pow(c, 3)) == s;
    }

    /*
     *  题目：将一个正整数分解质因数。例如：输入90,打印出90=2*3*3*5。
     *程序分析：对n进行分解质因数，应先找到一个最小的质数k，然后按下述步骤完成：
     *(1)如果这个质数恰等于n，则说明分解质因数的过程已经结束，打印出即可。
     *(2)如果n <> k，但n能被k整除，则应打印出k的值，并用n除以k的商,
     * 作为新的正整数你n,重复执行第一步。
     *(3)如果n不能被k整除，则用k+1作为k的值,重复执行第一步。
     */
    @Test
    public void problem4() {
        int n = 90;
        System.out.print(n+"=");
        for (int k = 2 ; k<=n/2;k++){
            if (n%k==0){
                System.out.print(k+"*");
                n = n/k;
                k = 2;
            }
        }
        System.out.println(n);
    }




    //题目：利用条件运算符的嵌套来完成此题：
    // 学习成绩> =90分的同学用A表示，60-89分之间的用B表示，60分以下的用C表示。
    @Test
    public void problem5() {
        int x;
        char grade;
        Scanner s = new Scanner(System.in);
        System.out.print("请输入一个成绩: ");
        x = s.nextInt();
        grade = x >= 90 ? 'A' : x >= 60 ? 'B' : 'C';
        System.out.println("等级为：" + grade);
    }


    /**
     * 题目：输入两个正整数m和n,求其最大公约数和最小公倍数。
     * 在循环中，只要除数不等于0，用较大数除以较小的数，将小的一个数作为下一轮循环的大数，
     * 取得的余数作为下一轮循环的较小的数，如此循环直到较小的数的值为0，返回较大的数，
     * 此数即为最大公约数，最小公倍数为两数之积除以最大公约数。
     */
    @Test
    public void problem6() {
        int n = 27216;
        int m = 15750;
        int maxGCD = gcd(n,m);
        int minLCM =  n*m/maxGCD;
        System.out.println("最大公约数为"+maxGCD+"最小公倍数为"+minLCM);
    }

    //计算最大公约数
    public  static  int gcd(int a  ,int b ){
        if (a%b==0){
            return a>b?b:a;//取出两个中较小的一个
        }
        return gcd(b,a%b);
    }


    //【程序7】
    //题目：输入一行字符，分别统计出其中英文字母、空格、数字和其它字符的个数。
    @Test
    public void problem7() {
        String i = "    123    String i = 题目：:输入一行字符，分别统计出其中英文字母、空格、数字和其它字符的个数 dasidhaoihw";
        int digital = 0; //数字
        int character = 0; //中英文字母
        int other = 0; // 其他字符
        int blank = 0;//空格
        int chineseCount = 0;//空格

        char[] a = i.toCharArray();
        for (char b : a) {
            if (b >= '0' && b <= '9') {
                digital++;
            } else if ((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')) {
                character++;
            } else if (b == ' ') {
                blank++;
            } else if (b >= 0x0391 && b <= 0xFFE5) { //中文unicode编码

                chineseCount++;
            } else {

                other++;
            }

        }
        System.out.println("中文: " + chineseCount);
        System.out.println("数字个数: " + digital);
        System.out.println("英文字母个数: " + character);
        System.out.println("空格个数: " + blank);
        System.out.println("其他字符个数:" + other);


    }


    //【程序8】
    //题目：求s=a+aa+aaa+aaaa+aa...a的值，其中a是一个数字。
    // 例如2+22+222+2222+22222(此时共有5个数相加)，几个数相加有键盘控制。
    public static void main(String ... o) {
        Scanner s = new Scanner(System.in);//
        int a = s.nextInt();// 输入数字
        int b = s.nextInt();// 输入累计次数
        int sum = 0;
        int tamp = 0;

        for (int i = 0; i < b; i++) {
            tamp = tamp + a;
            sum = sum + tamp;
            a = a * 10;
        }
        System.out.println(sum);
    }


    //【程序9】
    //题目：一个数如果恰好等于它的因子之和，这个数就称为 "完数 "。
    // 例如6=1+2+3.编程 找出1000以内的所有完数。
    @Test
    public void problem9() {
        IntStream.rangeClosed(1, 1000).filter((s) -> {
            int t = 0;
            for (int i = 1; i <= s / 2; i++) {
                if (s % i == 0) {
                    t = t + i;
                }
            }
            return t == s;
        }).forEach(System.out::println);


        System.out.println("1到1000的完数有： ");
        for (int i = 1; i < 1000; i++) {
            int t = 0;
            for (int j = 1; j <= i / 2; j++) {
                if (i % j == 0) {
                    t = t + j;
                }
            }
            if (t == i) {
                System.out.print(i + " ");
            }
        }

    }


    //题目：一球从100米高度自由落下，每次落地后反跳回原高度的一半;
    // 再落下，求它在 第10次落地时，共经过多少米 第10次反弹多高
    @Test
    public void problem10() {
        double distance = 100;

        int cishu = 10;
        double sumdistance = 0;
        double temp = 0;
        for (int i = 0; i < cishu; i++) {
            temp = distance / 2;


            sumdistance = add(sumdistance, distance, temp);
            distance = temp;
        }
        System.out.println("反弹" + distance + "   米");
        System.out.println("经过" + (sumdistance - temp) + "   米");


        //答案
        double h = 100, s = 100;
        for (int i = 1; i < 10; i++) {
            s = s + h;
            h = h / 2;
        }
        System.out.println("经过路程：" + s);
        System.out.println("反弹高度：" + h / 2);
    }


    public static Double add(Double v1, Double v2, Double v3) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        BigDecimal b3 = new BigDecimal(v3.toString());
        return b1.add(b2).add(b3).doubleValue();
    }



}